#include"GrammarSymbol.h"
using namespace std;
GrammarSymbol::GrammarSymbol(){
  Token_Num=0;
  Grammar_Num=0;
}
GrammarSymbol::~GrammarSymbol(){
  delete [] emission;
  delete [] binary;
}
void GrammarSymbol::setg_num(int g_num){
  Grammar_Num=g_num;
  b_len=g_num*g_num;
  binary=new double[g_num*g_num];
  for(int i=0;i<b_len;i++)binary[i]=0;
}
void GrammarSymbol::sett_num(int t_num){
  Token_Num=t_num;
  e_len=t_num;
  emission=new double[e_len];
  for(int i=0;i<e_len;i++)emission[i]=0;
}
void GrammarSymbol::readbinary(string line){
  istringstream cins(line);
  int l_id,r_id;
  double v;
  cins>>l_id;
  cins>>r_id;
  cins>>v;
  this->setbinary(l_id,r_id,v);
}

double readtyperule(std::string line){
  std::istringstream cins(line);
  std::string temp;
  double v;
  cins>>temp;
  cins>>v;
  return v;
}
void GrammarSymbol::reademission(string line){
  istringstream cins(line);
  int t_id;
  double v;
  cins>>t_id;
  cins>>v;
  this->setemission(t_id,v);
}

double GrammarSymbol::getemission(int t_id){
  assert(t_id<Token_Num);
  return emission[t_id]*e_type;
}
double GrammarSymbol::getbinary(int l_id,int r_id){
  return binary[this->twoD2oneD(l_id,r_id)]*b_type;
}
int GrammarSymbol::twoD2oneD(int l_id,int r_id){
  assert(l_id<Grammar_Num);
  assert(r_id<Grammar_Num);
  return l_id+r_id*Grammar_Num;
}
void GrammarSymbol::setemission(int t_id,double v){
    assert(t_id<Token_Num);
    e_change+=(v-emission[t_id])*(v-emission[t_id]);
    
    emission[t_id]=v;
}
void GrammarSymbol::setbinary(int l_id,int r_id,double v){
    assert(l_id<Grammar_Num);
    assert(r_id<Grammar_Num);
    int b_id=this->twoD2oneD(l_id,r_id);
    b_change+=(v-binary[b_id])*(v-binary[b_id]);
    binary[b_id]=v;
  }

std::istream& operator>>(std::istream& in,GrammarSymbol& s){
  std::string line;
  
  getline(in,line);//e_type
  s.e_type=readtyperule(line);
  getline(in,line);//b_type
  s.b_type=readtyperule(line);

  getline(in,line);//#beginbinary
  while(getline(in,line)){
    if(line[0]=='#')break;//#endbinary
    s.readbinary(line);
  }

  getline(in,line);//#beginemission
  while(getline(in,line)){
    if(line[0]=='#')break;//#endemission
    s.reademission(line);
  }

  return in;
}
std::ostream& operator<<(std::ostream& out,GrammarSymbol& s){
  out<<"e_type \t"<<s.e_type<<std::endl;
  out<<"b_type \t"<<s.b_type<<std::endl;

  out<<"#beginbinary"<<std::endl;
  for(int i=0;i<s.Grammar_Num;i++)
    for(int j=0;j<s.Grammar_Num;j++){
      double tempv=s.getbinary(i,j);
      if(tempv>Config::getdouble("minprobability"))
	out<<i<<"\t"<<j<<"\t"<<tempv<<std::endl;
    }
  out<<"#endbinary"<<std::endl;

  out<<"#beginemission"<<std::endl;
  for(int i=0;i<s.Token_Num;i++){
    double tempv=s.getemission(i);
    if(tempv>Config::getdouble("minprobability"))
	out<<i<<"\t"<<tempv<<std::endl;
  }
  out<<"#endemission"<<std::endl;

  return out;
}
void GrammarSymbol::resetchanges(){
  e_change=0;
  b_change=0;
  t_change=0;
}
double GrammarSymbol::last_change(){
    return sqrt(e_change+b_change+t_change);
}
void GrammarSymbol::settype_e(double v){t_change+=(e_type-v)*(e_type-v);e_type=v;}
void GrammarSymbol::settype_b(double v){t_change+=(b_type-v)*(b_type-v);b_type=v;}
